package ar.uade.edu.fain.ad.server.service.factory;

import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;

import ar.uade.edu.fain.ad.common.remote.CajaServicioRemoto;
import ar.uade.edu.fain.ad.common.remote.EmpleadoServicioRemoto;
import ar.uade.edu.fain.ad.common.remote.SalonServicioRemoto;
import ar.uade.edu.fain.ad.common.remote.SwingProcessRemoto;
import ar.uade.edu.fain.ad.server.dao.jpa.CajaJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.CierreCajaJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.ComisionJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.DepositoCentralJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.EmpleadoJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.FacturaJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.MedioPagoJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.MesaJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.MozoJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.NotaDevolucionJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.OrdenCompraJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.PedidoJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.PlatoJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.ProductoJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.SectorJpaDAO;
import ar.uade.edu.fain.ad.server.dao.jpa.UnidadJpaDAO;
import ar.uade.edu.fain.ad.server.service.CajaSRV;
import ar.uade.edu.fain.ad.server.service.EmpleadoSRV;
import ar.uade.edu.fain.ad.server.service.GeneralRemoto;
import ar.uade.edu.fain.ad.server.service.SalonSRV;
import ar.uade.edu.fain.ad.server.util.persistence.HibernateTransactionManager;
import ar.uade.edu.fain.ad.server.util.persistence.HibernateUtil;

public class RemoteServiceContext {

	private Map<String, Remote> services; 
	
	public RemoteServiceContext() {
		super();
		this.services = new HashMap<String, Remote>();
	}
	
	public Map<String, Remote> getServices() {
		return services;
	}
	
	public void init() {
		// Create DAOs
		MesaJpaDAO mesaJpaDAO = new MesaJpaDAO();
		PedidoJpaDAO pedidoJpaDAO = new PedidoJpaDAO();
		SectorJpaDAO sectorJpaDAO = new SectorJpaDAO();
		MozoJpaDAO mozoJpaDAO = new MozoJpaDAO();
		PlatoJpaDAO platoJpaDAO = new PlatoJpaDAO();
		ProductoJpaDAO productoJpaDAO = new ProductoJpaDAO();
		UnidadJpaDAO unidadJpaDAO = new UnidadJpaDAO();
		FacturaJpaDAO facturaJpaDAO = new FacturaJpaDAO();
		CajaJpaDAO cajaJpaDAO = new CajaJpaDAO();
		MedioPagoJpaDAO medioPagoJpaDAO = new MedioPagoJpaDAO();
		ComisionJpaDAO comisionJpaDAO = new ComisionJpaDAO();
		NotaDevolucionJpaDAO notaDevolucionJpaDAO = 
				new NotaDevolucionJpaDAO();
		OrdenCompraJpaDAO ordenCompraJpaDAO = new OrdenCompraJpaDAO();
		DepositoCentralJpaDAO depositoCentralJpaDAO = 
				new DepositoCentralJpaDAO();
		EmpleadoJpaDAO empleadoJpaDAO = new EmpleadoJpaDAO();
		CierreCajaJpaDAO cierreCajaJpaDAO = new CierreCajaJpaDAO();
		// Prepare DAOs
		productoJpaDAO.setUnidadDAO(unidadJpaDAO);
		platoJpaDAO.setProductoDAO(productoJpaDAO);
		sectorJpaDAO.setMesaDAO(mesaJpaDAO);
		pedidoJpaDAO.setMesaDAO(mesaJpaDAO);
		pedidoJpaDAO.setPlatoDAO(platoJpaDAO);
		facturaJpaDAO.setCajaDAO(cajaJpaDAO);
		facturaJpaDAO.setPedidoDAO(pedidoJpaDAO);
		facturaJpaDAO.setPlatoDAO(platoJpaDAO);
		depositoCentralJpaDAO.setProductoDAO(productoJpaDAO);
		ordenCompraJpaDAO.setProductoDAO(productoJpaDAO);
		final HibernateTransactionManager transactionManager = 
				HibernateTransactionManager.get();
		// Force Hibernate bootstrap
		HibernateUtil.get();
		// Create SRVs
		SalonSRV salonSRV = null;
		CajaSRV cajaSRV = null;
		GeneralRemoto generalRemotoSRV = null;
		EmpleadoSRV empleadoSRV = null;
		try {
			salonSRV = new SalonSRV();
			cajaSRV = new CajaSRV();
			generalRemotoSRV = new GeneralRemoto();
			empleadoSRV = new EmpleadoSRV();
		} catch (RemoteException e) {
			throw new IllegalStateException("Error creando beans.", e);
		}
		// Prepare SRVs
		salonSRV.setMesaDAO(mesaJpaDAO);
		salonSRV.setMozoDAO(mozoJpaDAO);
		salonSRV.setSectorDAO(sectorJpaDAO);
		salonSRV.setPedidoDAO(pedidoJpaDAO);
		salonSRV.setPlatoDAO(platoJpaDAO);
		salonSRV.setTransactionManager(transactionManager);
		cajaSRV.setTransactionManager(transactionManager);
		cajaSRV.setPedidoDAO(pedidoJpaDAO);
		cajaSRV.setCajaDAO(cajaJpaDAO);
		cajaSRV.setFacturaDAO(facturaJpaDAO);
		cajaSRV.setMedioPagoDAO(medioPagoJpaDAO);
		cajaSRV.setComisionDAO(comisionJpaDAO);
		cajaSRV.setCierreCajaDAO(cierreCajaJpaDAO);
		generalRemotoSRV.setProductoDAO(productoJpaDAO);
		generalRemotoSRV.setDepositoCentralDAO(depositoCentralJpaDAO);
		generalRemotoSRV.setNotaDevolucionDAO(notaDevolucionJpaDAO);
		generalRemotoSRV.setOrdenCompraDAO(ordenCompraJpaDAO);
		generalRemotoSRV.setTransactionManager(transactionManager);
		empleadoSRV.setEmpleadoDAO(empleadoJpaDAO);
		// Publish SRVs in internal registry
		getServices().put(
				CajaServicioRemoto.class.getCanonicalName(), cajaSRV);
		getServices().put(
				SalonServicioRemoto.class.getCanonicalName(), salonSRV);
		getServices().put(
				SwingProcessRemoto.class.getCanonicalName(), generalRemotoSRV);
		getServices().put(
				EmpleadoServicioRemoto.class.getCanonicalName(), empleadoSRV);
	}
	
	@SuppressWarnings("unchecked")
	public <T> T get(final Class<T> serviceClass) {
		try {
			return (T) getServices().get(serviceClass.getCanonicalName());
		} catch (ClassCastException cce) {
			throw new IllegalStateException(
					"Bootstrap con problemas de configuracion...", cce);
		}
	}
	
	
}
